﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace RabbitMqService.Worker
{
    public class WorkerManager
    {
        static WorkerManager instance = null;
        static object lockObj = new object();
        
        /// <summary>
        /// 线程安全的单例
        /// </summary>
        public static WorkerManager Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (lockObj)
                    {
                        if (instance == null)
                        {
                            instance = new WorkerManager();
                        }
                    }
                }
                return instance;
            }
        }

        private WorkerManager() {        
            WorkersInstance = new List<IWorker>();
            ThreadPool = new Dictionary<IWorker, Thread>();
        }
        /// <summary>
        /// 用于存储工作者的线程
        /// </summary>
        private Dictionary<IWorker, Thread> ThreadPool; 

        /// <summary>
        /// 保存已经开启工作的实例引用
        /// </summary>
       public  IList<IWorker> WorkersInstance { get; set; }
        /// <summary>
        /// 查找已经开启工作的实例引用
        /// </summary>
        /// <param name="worker"></param>
        /// <returns></returns>
        private IWorker FindWorkerInstance(IWorker worker)
        {
            foreach (var w in WorkersInstance)
            {
                if (w.GetType() == worker.GetType())
                {
                    return w;   
                }
            }
            return null;
        }
        /// <summary>
        /// 向Workers里面开始工作的类型,并创建个个工作线程放到ThreadPool 里面去
        /// </summary>
        /// <param name="worker"></param>
        private bool AddWorkers(IWorker worker)
        {
            if (FindWorkerInstance(worker) == null)
            {
                WorkersInstance.Add(worker);
                //新建一个线程设置为后台线程，并吧他添加到ThreadPool里面去
                Thread workerThread = new Thread(worker.DoWork);
                workerThread.IsBackground = true;
                ThreadPool.Add(worker, workerThread);
                return true;
            }
            else
            {
               
                return false;
            }

        }
        /// <summary>
        /// 把要停止的工作从WorKers里面删除,并吧线程从工作线程池中移除
        /// </summary>
        /// <param name="worker"></param>
        /// <returns></returns>
        private bool DeleteWorker(IWorker worker)
        {
            if ((FindWorkerInstance(worker) != null))
            {              
                    ThreadPool[worker].Abort();           
                    WorkersInstance.Remove(worker);
                    ThreadPool.Remove(worker);
                    return true;     
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 在后台开启一个线程并开始执行工作
        /// </summary>
        /// <param name="worker"></param>
        public  bool StartWork(IWorker worker)
        {        
            bool isSuccess = AddWorkers(worker);
            if (!isSuccess)
            {
                return false;
            }
            else
            {
                //开启要工作的线程
                ThreadPool[worker].Start();
                return true;
            }         
        }
        /// <summary>
        /// 停止给定的工作
        /// </summary>
        /// <param name="worker"></param>
        public bool StopWork(IWorker worker)
        {
            return DeleteWorker(worker);
        }

    }
}
